package com.example.nextgen.parser.excel.model;

import cn.hutool.core.util.StrUtil;

import java.util.*;
import java.util.function.Function;
import java.util.regex.Pattern;

/**
 * 数据类型枚举
 * 参数 pattern 正则匹配(0:无内容 1:键 2:值 3:合并 .:任意单个匹配) 如3011..表示一个垂直单列的数据布局
 * 参数 function 数据提取函数的实现方法
 * 此枚举类型声明了一个数据布局,以及如何从布局的根节点提取数据
 */
public enum DataType {

    ListVertical(Pattern.compile("3011.."), cellModelRoot -> {
        Map<String, Object> data = new LinkedHashMap<>();
        String rootKey = cellModelRoot.getContent().toString();
        List<Map<String, Object>> rootValue = new ArrayList<>();
        data.put(rootKey, rootValue);
        int rowIndex = 1;
        List<CellModel> keys = cellModelRoot.getRow(rowIndex);
        while (rowIndex < cellModelRoot.getRows()) {
            ++rowIndex;
            List<CellModel> row = cellModelRoot.getRow(rowIndex);
            Map<String, Object> listItem = new HashMap<>();
            for (int i = 0; i < keys.size(); i++) {
                listItem.put(keys.get(i).getContent().toString(), row.get(i).getContent());
            }
            rootValue.add(listItem);
        }
        return data;
    }),
    ListHorizontal(Pattern.compile("3102.."), cellModelRoot -> {
        Map<String, Object> data = new LinkedHashMap<>();
        String rootKey = cellModelRoot.getContent().toString();
        Map<String, Object> rootValue = new HashMap<>();
        data.put(rootKey, rootValue);
        int rowIndex = 0;
        List<CellModel> keys = cellModelRoot.getRow(rowIndex);
        keys = keys.subList(1, keys.size());
        while (rowIndex < cellModelRoot.getRows()) {
            ++rowIndex;
            List<CellModel> row = cellModelRoot.getRow(rowIndex);
            Map<String, Object> listItem = new HashMap<>();
            for (int i = 0; i < keys.size(); i++) {
                listItem.put(keys.get(i).getContent().toString(), row.get(i).getContent());
            }
            rootValue.putAll(listItem);
        }
        return data;
    }),
    MapVertical(Pattern.compile("30120."), cellModelRoot -> {
        Map<String, Object> data = new HashMap<>();
        String rootKey = cellModelRoot.getContent().toString();
        Map<String, Object> items = new HashMap<>();
        data.put(rootKey, items);
        int rowIndex = 1;
        while (rowIndex < cellModelRoot.getRows()) {
            List<CellModel> row = cellModelRoot.getRow(rowIndex);
            Map<String, Object> item = new HashMap<>();
            item.put(row.get(0).getContent().toString(), row.get(1).getContent());
            items.putAll(item);
            ++rowIndex;
        }
        return data;
    }),
    MapHorizontal(Pattern.compile("3101.0"), cellModelRoot -> {
        String rootKey = cellModelRoot.getContent().toString();
        Map<String, Object> item = new HashMap<>();
        item.put(cellModelRoot.getRight().getContent().toString(),
                cellModelRoot.getRight().getRight().getContent());
        Map<String, Object> items = new HashMap<>(item);
        int rowIndex = 0;
        while (rowIndex < cellModelRoot.getRows()) {
            List<CellModel> row = cellModelRoot.getRow(rowIndex);
            item = new HashMap<>();
            item.put(row.get(0).getContent().toString(), row.get(1).getContent());
            items.putAll(item);
            ++rowIndex;
        }
        Map<String, Object> data = new HashMap<>();
        data.put(rootKey, items);
        return data;
    }),
    ArrayVertical(Pattern.compile("102002"), cellModelRoot -> {
        Map<String, Object> data = new HashMap<>();
        String rootKey = cellModelRoot.getContent().toString();
        List<Object> items = new ArrayList<>();
        data.put(rootKey, items);
        for (int i = 1; i < cellModelRoot.getRows(); i++) {
            items.add(cellModelRoot.getRow(i).get(0).getContent());
        }
        return data;
    }),
    KeyValueVertical(Pattern.compile("1.2..."), cellModelRoot -> {
        Map<String, Object> data = new HashMap<>();
        String rootKey = cellModelRoot.getContent().toString();
        String value = cellModelRoot.getBottom().getContent().toString();
        data.put(rootKey, value);
        return data;
    }),
    KeyValueHorizontal(Pattern.compile("12...."), cellModelRoot -> {
        Map<String, Object> data = new HashMap<>();
        String rootKey = cellModelRoot.getContent().toString();
        Object value = cellModelRoot.getRight().getContent();
        data.put(rootKey, value);
        return data;
    }),
    ;

    public static final int NO_CELL = 0;
    public static final int KEY_CELL = 1;
    public static final int VALUE_CELL = 2;
    public static final int MERGED_CELL = 3;

    //0123.
    //根 右 下 下右 右右 下下
    final Pattern expression;

    final Function<CellModel, Map<String, Object>> handlerFunction;

    DataType(Pattern expression, Function<CellModel, Map<String, Object>> handlerFunction) {
        this.expression = expression;
        this.handlerFunction = handlerFunction;
    }

    public static String getLayout(CellModel cellModel) {
        CellModel cellModelRoot = cellModel.getRoot();
        int root, right, bottom, bottomRight = NO_CELL, rightRight = NO_CELL, bottomBottom = NO_CELL;
        String layout = "";
        if (cellModelRoot == null) {
            return layout;
        }
        root = getCellProperty(cellModelRoot);
        right = getCellProperty(cellModelRoot.getRight());
        bottom = getCellProperty(cellModelRoot.getBottom());
        if (bottom != NO_CELL) {
            bottomRight = getCellProperty(cellModelRoot.getBottom().getRight());
        }
        if (right != NO_CELL) {
            if (bottomRight == NO_CELL) {
                bottomRight = getCellProperty(cellModelRoot.getRight().getBottom());
            }
            rightRight = getCellProperty(cellModelRoot.getRight().getRight());
        }
        if (bottom != NO_CELL) {
            bottomBottom = getCellProperty(cellModelRoot.getBottom().getBottom());
        }
        layout = "" + root + right + bottom + bottomRight + rightRight + bottomBottom;
        return layout;
    }

    public static int getCellProperty(CellModel cellModel) {
        if (cellModel == null) {
            return NO_CELL;
        }
        if (cellModel.isMerged() && cellModel.isBold()) {
            return MERGED_CELL;
        }
        if (cellModel.isBold()) {
            return KEY_CELL;
        }
        return VALUE_CELL;
    }

    public static DataType of(CellModel cellModel) {
        String layout = getLayout(cellModel);
        if (StrUtil.isBlank(layout)) {
            return null;
        }
        if (ListVertical.expression.matcher(layout).matches()) {
            return ListVertical;
        }
        if (ListHorizontal.expression.matcher(layout).matches()) {
            return ListHorizontal;
        }
        if (MapVertical.expression.matcher(layout).matches()) {
            return MapVertical;
        }
        if (MapHorizontal.expression.matcher(layout).matches()) {
            return MapHorizontal;
        }
        if (ArrayVertical.expression.matcher(layout).matches()) {
            return ArrayVertical;
        }
        if (KeyValueVertical.expression.matcher(layout).matches()) {
            return KeyValueVertical;
        }
        if (KeyValueHorizontal.expression.matcher(layout).matches()) {
            return KeyValueHorizontal;
        }
        return null;
    }

    public static Map<String, Object> extractData(CellModel cellModelRoot) {
        DataType dataType = of(cellModelRoot);
        if (dataType == null) {
            return new HashMap<>();
        }
        return dataType.handlerFunction.apply(cellModelRoot);
    }
}
